package com.numberone.iotplatform.service.impl;

import com.numberone.iotplatform.dto.LocationDTO;
import com.numberone.iotplatform.dto.LocationMoveDTO;
import com.numberone.iotplatform.entity.Location;
import com.numberone.iotplatform.exception.ResourceNotFoundException;
import com.numberone.iotplatform.repository.LocationRepository;
import com.numberone.iotplatform.service.LocationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; // 引入事务注解
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class LocationServiceImpl implements LocationService {

    @Autowired
    private LocationRepository locationRepository;

    /**
     * 获取位置树。
     * 推荐前端进行过滤，因此后端默认返回完整树。
     * 如果提供了 nameFilter，则返回一个扁平的过滤列表（可以根据需求调整为重构树）。
     */
    @Override
    @Transactional(readOnly = true) // 只读事务，提高查询性能
    public List<LocationDTO> getLocationTree(String nameFilter) {
        if (!StringUtils.hasText(nameFilter)) {
            // 获取所有根节点 (parent_id is NULL)
            List<Location> rootLocations = locationRepository.findByParentId(null);
            // 递归地将实体转换为 DTO
            return rootLocations.stream().map(this::convertToDto).collect(Collectors.toList());
        } else {
            // 过滤模式：查找所有名称匹配的节点
            List<Location> allLocations = locationRepository.findAll();
            return allLocations.stream()
                    .filter(loc -> loc.getName().toLowerCase().contains(nameFilter.toLowerCase()))
                    .map(this::convertToDtoSimple) // 转换为不带 children 的简单 DTO
                    .collect(Collectors.toList());
        }
    }

    /**
     * 创建一个新的位置节点。
     */
    @Override
    @Transactional
    public LocationDTO createLocation(LocationDTO locationDTO) {
        Location location = new Location();
        location.setName(locationDTO.getName());

        // 如果提供了 parentId，则查找并设置父节点
        if (locationDTO.getParentId() != null) {
            Location parent = locationRepository.findById(locationDTO.getParentId())
                    .orElseThrow(() -> new ResourceNotFoundException("Parent location not found with id: " + locationDTO.getParentId()));
            location.setParent(parent);
        }

        Location savedLocation = locationRepository.save(location);
        return convertToDto(savedLocation);
    }

    /**
     * 【补全】更新一个已存在的位置节点。
     * 目前只支持更新名称。
     */
    @Override
    @Transactional
    public LocationDTO updateLocation(Long id, LocationDTO locationDTO) {
        // 查找要更新的节点，如果不存在则抛出异常
        Location locationToUpdate = locationRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Location not found with id: " + id));

        // 更新名称
        locationToUpdate.setName(locationDTO.getName());

        // 如果需要移动节点，可以在这里添加更新 parent 的逻辑
        // if (locationDTO.getParentId() != null) { ... }

        Location updatedLocation = locationRepository.save(locationToUpdate);
        return convertToDto(updatedLocation);
    }


    /**
     * 将 Location 实体递归地转换为 LocationDTO，用于构建完整的树形结构。
     */
    private LocationDTO convertToDto(Location location) {
        LocationDTO dto = new LocationDTO();
        dto.setId(location.getId());
        dto.setName(location.getName());
        if (location.getParent() != null) {
            dto.setParentId(location.getParent().getId());
        }

        // 递归转换子节点
        if (location.getChildren() != null && !location.getChildren().isEmpty()) {
            dto.setChildren(location.getChildren().stream()
                    .map(this::convertToDto)
                    .collect(Collectors.toList()));
        }
        return dto;
    }

    /**
     * 将 Location 实体转换为简化的 LocationDTO，不包含子节点。
     * 主要用于过滤后的扁平列表。
     */
    private LocationDTO convertToDtoSimple(Location location) {
        LocationDTO dto = new LocationDTO();
        dto.setId(location.getId());
        dto.setName(location.getName());
        if (location.getParent() != null) {
            dto.setParentId(location.getParent().getId());
        }
        return dto;
    }

    @Override
    @Transactional
    public void deleteLocation(Long id) {
        // 【修复】确保删除前检查是否存在
        Location locationToDelete = locationRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Location not found with id: " + id));

        locationRepository.delete(locationToDelete);
    }

    @Override
    @Transactional
    public void moveLocation(Long locationId, Long targetParentId) {
        Location nodeToMove = locationRepository.findById(locationId)
                .orElseThrow(() -> new ResourceNotFoundException("Location to move not found"));

        // 防止将节点移动到自身或其子节点下，避免循环引用
        if (targetParentId != null && isChildOf(targetParentId, locationId)) {
            throw new IllegalArgumentException("Cannot move a location into one of its own descendants.");
        }

        if (targetParentId != null) {
            Location newParent = locationRepository.findById(targetParentId)
                    .orElseThrow(() -> new ResourceNotFoundException("Target parent location not found"));
            nodeToMove.setParent(newParent);
        } else {
            nodeToMove.setParent(null); // 移动到根节点
        }
        locationRepository.save(nodeToMove);
        // TODO: 完整的实现还需要递归更新所有子节点的 depth 和 path
    }

    // 辅助方法，检查 targetId 是否是 childId 的子孙
    private boolean isChildOf(Long targetId, Long childId) {
        Location target = locationRepository.findById(targetId).orElse(null);
        while (target != null) {
            if (target.getId().equals(childId)) {
                return true;
            }
            target = target.getParent();
        }
        return false;
    }


    @Override
    @Transactional
    public void updateSortOrder(List<Long> locationIdsInOrder) {
        for (int i = 0; i < locationIdsInOrder.size(); i++) {
            Long id = locationIdsInOrder.get(i);
            int finalI = i;
            locationRepository.findById(id).ifPresent(location -> {
                location.setSortOrder(finalI);
                // locationRepository.save(location); // 在事务内，此行可省略
            });
        }
    }

    @Override
    public String buildLocationPath(Location location) {
        if (location == null) {
            return "";
        }
        if (location.getParent() != null) {
            return buildLocationPath(location.getParent()) + " / " + location.getName();
        }
        return location.getName();
    }
}